<?php
	/**
	 * PkModel File.
	 * 
	 * @author Brian Bal <brian@youbeqb.com>
	 * @version 1.0
	 * @package pink-koala
	 */
	
	/**
	 * PkModel class
	 *
	 * @package pink-koala
	 * @author Brian Bal
	 **/
	
	Abstract Class PkModel Implements ArrayAccess
	{
		static public $instances = array();
		private $table_name;
		private $primary_key;
		
		public function __construct($params = null)
		{
			$this->primary_key = "id";
			$this->table_name = plural(uncamelize($this->getClassName()));
			
			
			
			$table_columns = $this->getTableColumns();
			
			foreach($table_columns as $table_column)
			{
				$this->{$table_column['Field']} = $table_column['Default'];
				
				if($table_column['Key'] == 'PRI')
				{
					$this->primary_key = $table_column['Field'];
					$this->{$table_column['Field']} = 0;
				}
			}
			
			$table_columns = null;
			
			
			$this->set($params);
			
		}
		
		public function getTableColumns()
		{
			return PkDatabase::tableSchema($this->table_name);
		}
		
		public function getTableName()
		{
			return $this->table_name;
		}
		
		public function __toString()
		{
			return $this->{$this->primary_key};
		}
		
		abstract public function getClassName();
		
		
		
		
		
		///
		///		Database CRUD Methods for class
		///
		
		/**
		 * 	calls update or create, if this instance has an id set create is call
		 *	if id is 0 or null update is called
		 * 	@return boolean
		 */
		function save()
		{
			// check if update or create is needed
			if($this->{$this->primary_key} == 0)
			{
				return $this->create();
			}else{
				return $this->update();
			}
		}
		
		/**
		 * create inserts a new row into the database
		 * @return boolean
		 */
		function create() 
		{
			$values = "";
			$columns = "";
			$count = 0;
			
			$table_columns = $this->getTableColumns();
			
			foreach($table_columns as $table_column)
			{
				$comma = ", ";
				if($count == 0){ $comma = ""; }
				
				$values .= $comma . "'" . $this->{$table_column['Field']} . "'";
				$columns .= $comma . "`" . $table_column['Field'] . "`";
				
				$count ++;
			}
			
			// build the query
			$sql = "INSERT INTO 
				`$this->table_name`
				(
					$columns
				)
				VALUES 
				(
					$values
				)";
			
			//echo "<pre>\n$sql\n</pre>";
			
			// run the query
			if(mysql_query($sql))
			{
				if(! $this->{$this->primary_key} = mysql_insert_id())
				{
					return false;
				}
			}else{
				return false;
			}
			
			return true;
		}
		
		/**
		 * update runs a update query for the current object
		 * @return boolean
		 */
		function update()
		{
			// check that the primary key is set before doing a update
			if($this->{$this->primary_key} == 0){ return false; }
			
			$sets = "";
			$count = 0;
			
			$table_columns = $this->getTableColumns();
			
			foreach($table_columns as $table_column)
			{
				$comma = ", ";
				if($count == 0){ $comma = ""; }
				
				$sets .= $comma . "`" . $table_column['Field'] . "` = " . "'" . $this->{$table_column['Field']} . "'";
				
				$count ++;
			}
			
			// build the query
			$sql = "UPDATE 
				`$this->table_name`
			SET
				$sets
			WHERE
				`$this->primary_key`= '" . $this->{$this->primary_key} . "'
			";
			
			//echo "<pre>\n$sql\n</pre>";
			
			// run the query
			if(! mysql_query($sql))
			{
				return false;
			}
			
			return true;
		}
		
		/**
		 * loads a model by its primary key from the datapk.
		 * It also loads the order_items by calling loadOrderItems()
		 * @param integer $id
		 * @return boolean
		 */
		function load($id = null)
		{
			// check that the primary key is set before doing a load
			if($id == null){ $id = $this->{$this->primary_key}; }
			
			$columns = "";
			$count = 0;
			
			$table_columns = $this->getTableColumns();
			
			foreach($table_columns as $table_column)
			{
				$comma = ", ";
				if($count == 0){ $comma = ""; }
				
				$columns .= $comma . "`" . $table_column['Field'] . "`";
				
				$count ++;
			}
			
			// build the query
			$sql = "SELECT
				$columns
			FROM 
				`$this->table_name`
			WHERE
				`$this->primary_key`= '" . $id . "'
			";
			
			//echo "<pre>\n$sql\n</pre>";
			
			// run the query and get results
			$result = mysql_query($sql);
			if($row = mysql_fetch_array($result))
			{
				foreach($row as $key => $val)
				{
					$this->$key = $val;
				}
				
			}else{
				return false;
			}
			
			return true;
		}
		
		/**
		 * loads a model by the conditions passed
		 * It also loads the order_items by calling loadOrderItems()
		 * @param string $condition
		 * @param string $order
		 * @param string $offset
		 * @return boolean
		 */
		function loadBy($condition = "first", $order = "none", $offset = "none")
		{
			// build query parts
			$where = "";
			if($condition != "all") { $where = "WHERE $condition"; }
			
			$offset_limit = "";
			if($offset != "none") { $offset_limit = "$offset_limit OFFSET $offset"; }
			
			
			$order_by = "";
			if($condition == "first")
			{
				$order_by = "`$this->primary_key` ASC";
			}else if($condition == "last"){
				$order_by = "`$this->primary_key` DESC";
			}
			
			if($order != "none") { $order_by = "ORDER BY $order"; }
			
			$columns = "";
			$count = 0;
			
			$table_columns = $this->getTableColumns();
			
			foreach($table_columns as $table_column)
			{
				$comma = ", ";
				if($count == 0){ $comma = ""; }
				
				$columns .= $comma . "`" . $table_column['Field'] . "`";
				
				$count ++;
			}
			
			// build the query
			$sql = "SELECT
				$columns
			FROM 
				`$this->table_name`
			$where
			$order_by
			$offset_limit
			LIMIT 1
			";
			
			//echo "<pre>\n$sql\n</pre>";
			
			// run the query and get results
			if($result = mysql_query($sql))
			{
				if($row = mysql_fetch_array($result))
				{
					foreach($row as $key => $val)
					{
						$this->$key = $val;
					}

				}else{
					return false;
				}
			}else{
				trigger_error("Not a valid MySQL Query ($sql)", E_USER_WARNING);
				return false;
			}
			
			return true;
		}
		
		
		/**
		 * deletes the current order and its order items from the datapk
		 * @return boolean
		 */
		function destroy()
		{
			if($this->{$this->primary_key} == 0){ return false; }
			
			// build the query
			$sql = "DELETE FROM `$this->table_name` WHERE `$this->primary_key`= '" . $this->{$this->primary_key} . "'";
			
			// run the query
			if(! mysql_query($sql))
			{
				return false;
			}
			
			$table_columns = $this->getTableColumns();
			
			foreach($table_columns as $table_column)
			{
				$this->{$table_column['Field']} = $table_column['Default'];
				
				if($table_column['Key'] == 'PRI')
				{
					$this->{$table_column['Field']} = 0;
				}
			}
			
			return true;
		}
		
		
		
		
		
		
		///
		///		get and set methods
		///
		
		function set($params)
		{
			if(is_array($params))
			{
				foreach($params as $key => $value)
				{
					if(isset($this->$key))
					{
						$function = "set" . camelize($key);
						$this->$function(sanitize($value));
					}
				}
			}
		}
		
		function __call( $method, $args )
		{
			if( preg_match( "/set(.*)/", $method, $found ) )
			{
				$key = uncamelize($found[1]);
				if(array_key_exists($key, $this))
				{
					$this->$key = $args[0];
					return true;
				}
			}
			
		    else if( preg_match( "/get(.*)/", $method, $found ) )
			{
				$key = uncamelize($found[1]);
				if(array_key_exists($key, $this))
				{
					return $this->$key;
				}
			}
			
			else if( preg_match( "/findBy(.*)/", $method, $found ) )
			{
				$key = uncamelize($found[1]);
				if(!isset($args[0])){ return false; }
				
				$value = $this->sanitize($args[0]);
				$order = "none";
				$limit = "none";
				$offset = "none";
				
				if(!isset($args[1])){ $order = $this->sanitize($args[1]); }
				if(!isset($args[2])){ $limit = $this->sanitize($args[2]); }
				if(!isset($args[3])){ $offset = $this->sanitize($args[3]); }
				
				return $this->find("$key = '$value'", $order, $limit, $offset);
			}
			
			else if( preg_match( "/loadBy(.*)/", $method, $found ) )
			{
				$key = uncamelize($found[1]);
				if(!isset($args[0])){ return false; }
				
				$value = $this->sanitize($args[0]);
				$order = "none";
				$limit = "none";
				
				if(!isset($args[1])){ $order = $this->sanitize($args[1]); }
				if(!isset($args[2])){ $limit = $this->sanitize($args[2]); }
				
				return $this->loadBy("$key = '$value'", $order, $offset);
			}
			
			trigger_error("($method) Method does not exist", E_USER_ERROR);
		}
		
		public function getPrimaryKey()
		{
			return $this->primary_key;
		}
		
		public function sanitize($var)
		{
			if(is_string($var))
			{
				$var = mysql_real_escape_string(stripslashes($var));
				return $var;
			}

			if(is_integer($var) || is_float($var))
			{
				$var = $var + 0;
				return $var;
			}

			return false;
		}
		
		
		
		
		
		// ArrayAccess Implementation
		
		function offsetExists($offset)
		{
			return isset($this->$offset);
		}
		
		function offsetGet($offset)
		{
			return $this->get($offset);
		}
		
		function offsetSet($offset, $value)
		{
			$this->$offset = $value;
		}
		
		function offsetUnset($offset)
		{
			unset($this->$offset);
		}
		
		
		
		//
		//		PkGatewayStuff
		//
		
		static public function gateway($sender)
		{
			if (!array_key_exists($sender, self::$instances))
			{
				self::$instances[$sender] =& new PkGateway($sender);
			}
			
			return self::$instances[$sender];
		}
	}
?>